package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.constants.TradeErrorInfo;
import com.tianji.learning.domain.dto.LearningPlanDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.service.ILearningLessonService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author yangyu
 * @since 2023-07-21
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {
    private final CourseClient courseClient;

    /**
     * 添加课程到课程表
     *
     * @param userId    用户id
     * @param courseIds 课程id
     */
    @Override
    public void addUserLessons(Long userId, List<Long> courseIds) {
        //1.根据课程id集合查询课程简单信息
        List<CourseSimpleInfoDTO> courseInfoDTOS = courseClient.getSimpleInfoList(courseIds);
        //判断课程是否存在，不存在则抛异常
        if (ObjectUtil.isEmpty(courseInfoDTOS)) {
            //课程信息不存在，无法添加到课表
            throw new BizIllegalException(TradeErrorInfo.COURSE_NOT_EXISTS);
        }

        //课程表集合
        ArrayList<LearningLesson> list = new ArrayList<>(courseInfoDTOS.size());

        //2.循环遍历所有课程消息，处理LearningLesson数据
        for (CourseSimpleInfoDTO courseInfoDTO : courseInfoDTOS) {
            LearningLesson lesson = new LearningLesson();

            //2.1.设置课程的过期时间
            Integer validDuration = courseInfoDTO.getValidDuration(); //有效期
            //防止空指针，validDuration可能为null，表示永久不过期
            if (validDuration != null && validDuration > 0) {
                LocalDateTime now = LocalDateTime.now();
                //计算过期时间
                LocalDateTime expireTime = now.plusMonths(validDuration);
                lesson.setExpireTime(expireTime);
            }

            //2.2.填充userId和courseId
            lesson.setCreateTime(LocalDateTime.now());
            lesson.setUserId(userId);
            lesson.setCourseId(courseInfoDTO.getId());
            //将课程添加到课表集合中
            list.add(lesson);
        }

        //3.批量新增课程到课程表
        saveBatch(list);
    }


    /**
     * 2.分页查询我的课表
     *
     * @param pageQuery 分页请求参数
     * @return 分页结果
     */
    @Override
    public PageDTO<LearningLessonVO> queryMyLessons(PageQuery pageQuery) {
        //1.获取当前用户id
        Long userId = UserContext.getUser();

        //2.分页查询-当前用户的课表数据
        //select * from learning_lesson where user_id = #{userId} order by latest_learn_time limit 0, 5
        Page<LearningLesson> lessonPage = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                //指定默认排序字段，指定默认排序规则为降序。参数为null则采用
                .page(pageQuery.toMpPage("latest_learn_time", false));

        List<LearningLesson> lessonList = lessonPage.getRecords();
        if (CollUtils.isEmpty(lessonList)) {
            return PageDTO.empty(lessonPage);
        }

        //3.查询课程信息
        //3.1.一个课表，包含多个课程信息，先遍历课表集合，获取每个课程id
        Set<Long> courseIds = lessonList.stream().map(LearningLesson::getCourseId).collect(Collectors.toSet());

        //3.2.根据课程id查询课程信息
        List<CourseSimpleInfoDTO> courseInfoList = courseClient.getSimpleInfoList(courseIds);
        if (CollUtils.isEmpty(courseInfoList)) {
            // 课程不存在，无法添加
            throw new BadRequestException("课程信息不存在！");
        }

        //3.3.把课程集合处理成Map，key是courseId，值是course本身，方便封装VO
        Map<Long, CourseSimpleInfoDTO> courseMap = courseInfoList.stream()
                //收集转为Map集合
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));

        //4.封装VO返回
        ArrayList<LearningLessonVO> lessonVOList = new ArrayList<>(lessonList.size());

        //4.1.循环遍历，把LearningLesson转为VO
        for (LearningLesson lesson : lessonList) {
            //4.2.拷贝基础属性到VO
            LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);

            //4.3.获取课程信息，填充到VO
            CourseSimpleInfoDTO cInfo = courseMap.get(vo.getCourseId());
            vo.setCourseName(cInfo.getName());  //课程名称
            vo.setCourseCoverUrl(cInfo.getCoverUrl());  //课程封面url
            vo.setSections(cInfo.getSectionNum());  //课程章节总数量

            //4.4.将每一个vo存入VO集合
            lessonVOList.add(vo);
        }

        return PageDTO.of(lessonPage, lessonVOList);
    }


    /**
     * 7.校验指定课程是否是课表中的有效课程（Feign接口）
     *
     * @param courseId 课程id
     * @return 有效则返回lessonId
     */
    @Override
    public Long isLessonValid(Long courseId) {
        //1.获取登录用户id
        Long userId = UserContext.getUser();

        //2.根据用户id，课程id，查询课表信息
        LearningLesson lesson = queryByUserAndCourseId(userId, courseId);

        //3.判断课程是否存在，状态是否失效
        if (lesson == null || LessonStatus.EXPIRED.equals(lesson.getStatus())) {
            //无效，则返回null
            return null;
        }
        //有效，则返回lessonId
        return lesson.getId();
    }


    /**
     * 8、根据用户ID和课程ID查询  ==> 课表信息
     *
     * @param userId   用户id
     * @param courseId 课程id
     * @return 课表信息
     */
    @Override
    public LearningLesson queryByUserAndCourseId(Long userId, Long courseId) {
        //查询课表，返回课表信息
        return getOne(Wrappers.<LearningLesson>lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId));
    }


    /**
     * 查询我最近正在学习的课程
     * @return 课程表信息
     */
//    @Override
//    public LearningLessonVO queryMyCurrentLesson() {
//        //1.获取当前登录用户id
//        Long userId = UserContext.getUser();
//
//        //2.根据用户id查询课表，根据latest_learn_time进行降序
//        List<LearningLesson> list = list(Wrappers.<LearningLesson>lambdaQuery()
//                .eq(LearningLesson::getUserId, userId)
//                .orderByDesc(LearningLesson::getLatestLearnTime)
//                .last("limit 1"));
//
//        //3.拿到最近学习的课程信息
//
//        //4.封装VO返回
//
//        return null;
//    }


    /**
     * 创建学习计划
     *
     * @param learningPlanDTO 课程id，计划每周学习频率
     */
    @Override
    public void createLearningPlan(LearningPlanDTO learningPlanDTO) {
        //1.获取当前用户id
        Long userId = UserContext.getUser();

        //2.查询课表中当前用户的，指定课程有关的数据
        LearningLesson lesson = queryByUserAndCourseId(userId, learningPlanDTO.getCourseId());

        //2.根据userId，课程id，修改课程表中的课程status，和指定的每周学习章节数量
        update(Wrappers.<LearningLesson>lambdaUpdate()
                .eq(LearningLesson::getUserId, userId)   //==userId
                .eq(LearningLesson::getCourseId, learningPlanDTO.getCourseId())//==courseId
                //课表学习计划状态为：没有计划        才修改为：计划进行中
                .set(lesson.getPlanStatus() == PlanStatus.NO_PLAN, LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING)
                .set(LearningLesson::getWeekFreq, learningPlanDTO.getFreq()));   //Set weekFreq = Freq
    }


}
